package pl.asoft.nbp.util;

import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import pl.asoft.nbp.exception.SystemException;
import pl.asoft.nbp.model.Currency;
import pl.asoft.nbp.model.ExchangeRate;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;

/**
 * Created by rbiedrawa on 2014-12-01.
 */
public class DocumentParser {
    private static final Logger LOG = Logger.getLogger(DocumentParser.class);
    private Collection<ExchangeRate> exchangeRateTable = Collections
            .synchronizedList(new ArrayList<>());

    public static URLConnection openConnection(String uri) {
        URLConnection connection = null;
        try {
            URL url = new URL(uri);
            connection = url.openConnection();
        } catch (IOException e) {
            throw new SystemException(e.getMessage());
        }
        return connection;
    }

    public void parse(String url, final String currency) {
        try {
            URLConnection connection = openConnection(url);
            connection.setRequestProperty("Content-Type", "text/xml");

            HttpURLConnection httpConnection = (HttpURLConnection) connection;

            if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {

                // DOM Factory
                DocumentBuilderFactory factory = DocumentBuilderFactory
                        .newInstance();
                factory.setFeature(
                        "http://apache.org/xml/features/nonvalidating/load-external-dtd",
                        false);

                // Parsing the document
                DocumentBuilder documentBuilder = factory
                        .newDocumentBuilder();
                Document document = documentBuilder.parse(httpConnection.getInputStream());
                document.getDocumentElement().normalize();


                DateTime date = new DateTime(document.getElementsByTagName("data_publikacji").item(0).getTextContent());

                NodeList position = document
                        .getElementsByTagName("pozycja");
                addData(exchangeRateTable, position, date.toDate(), currency);

            }

        } catch (IOException | ParserConfigurationException | SAXException e) {
            LOG.error("Error: ", e);
            LOG.error(e.getStackTrace());
            throw new SystemException(e.getMessage());
        }
    }

    private void addData(Collection<ExchangeRate> exchangeRates, NodeList position, Date date, String currency) {
        for (int i = 0; i < position.getLength(); i++) {
            Node n = position.item(i);
            if (n.getNodeType() == Node.ELEMENT_NODE) {

                Element e = (Element) n;
                final ExchangeRate exchangeRate = new ExchangeRate();
                if (currency.equals("ALL")) {
                    assemblyExchangeRate(date, e, exchangeRate);
                    exchangeRates.add(exchangeRate);
                } else if (e.getElementsByTagName("kod_waluty").item(0)
                        .getTextContent().equals(currency)) {
                    assemblyExchangeRate(date, e, exchangeRate);
                    exchangeRates.add(exchangeRate);
                }
            }
        }
    }

    private void assemblyExchangeRate(Date date, Element e, ExchangeRate exchangeRate) {
        exchangeRate.setCurrency(new Currency());
        exchangeRate.setDateOfPublication(date);
        exchangeRate.getCurrency().setName(e.getElementsByTagName("nazwa_waluty").item(0).getTextContent());
        exchangeRate.getCurrency().setShortName(e.getElementsByTagName("kod_waluty").item(0).getTextContent());
        exchangeRate.getCurrency().setConversion(Double.parseDouble(e.getElementsByTagName("przelicznik").item(0).getTextContent()));
        exchangeRate.setPrice(BigDecimal.valueOf(Double.valueOf(e.getElementsByTagName(
                "kurs_sredni").item(0).getTextContent().replace(",", "."))));
    }

    public Collection<ExchangeRate> getExchangeRateTable() {
        return exchangeRateTable;
    }
}
